<?php
/*------------------------------------------------------------------
 | Software: APHP - A PHP TOP Framework
 | Site: https://aphp.top
 |------------------------------------------------------------------
 | (C)2020-2025 无念<24203741@qq.com>,All Rights Reserved.
 |-----------------------------------------------------------------*/
declare(strict_types=1);
namespace extend\layui;
use aphp\core\Config;
use aphp\core\Single;

class Form
{
    use Single;

    // mode 0 新增 1 修改 2 生成 设置lay-reqtext='请输入'
    public function make(array $vo, int $mode = 0, string $append = ''): string
    {
        $attr = str_to_array($vo['form_attr']); // 表单属性
        if ($vo['lay_verify'] != 'none') {
            $attr['lay-verify'] = $vo['lay_verify']; // 验证属性
        }
        $name = $vo['field_name']; // 表单名称
        $value = $this->_parse_value($vo, $mode); // 表单值
        $options = $this->_parse_options($vo, $mode); // 表单选项
        if (in_array($vo['form_type'], ['radio', 'select', 'selects'])) {
            // 多选下拉框
            if ($vo['form_type'] == 'selects') {
                $attr['xm-select'] = $vo['field_name'];
                $attr['xm-select-skin'] = 'normal';
            }
            // 生成单选框 下拉框
            $attr = $this->_attr_str($attr);
            if ($mode == 2) {
                $input = $vo['form_type'] == 'radio' ? form_radio($name, $options, $value, $attr) : form_select($name, $options, $value, $attr);
            } else {
                if (!is_numeric($value) && !str_starts_with($value, '$')) {
                    $value = "'" . $value . "'";
                }
                $fn = $vo['form_type'] == 'radio' ? 'form_radio' : 'form_select';
                $input = '{:'.$fn.'(\'' . $name . '\', '.$options.', '.$value.', \''.$attr.'\')}';
            }
        } elseif ($vo['form_type'] == 'textarea' || $vo['form_type'] == 'tinymce') {
            // 生成文本域
            $attr['placeholder'] = $vo['form_tips'] ?: '请输入' . $vo['field_title'];
            $attr['class'] = 'layui-textarea';
            $extend = '';
            if ($vo['form_type'] == 'tinymce') {
                $attr['class'] .= ' editor-tinymce';
                $attr['data-api'] = url('api/upload').'?api=image'; // 编辑器图片上传接口
                $extend = '<p style="color:#009688;">Tips：可复制图库中的图片地址插入编辑器。</p>';
            }
            $attr = $this->_attr_str($attr);
            $input = $extend.'<textarea name="' . $name . '" id="editor-' . $name . '"' . $attr . '>' . $value . '</textarea>';
        } elseif ($vo['form_type'] == 'switch') {
            // 生成开关
            if ($mode == 1) {
                $checked = '{if $vo[\'' . $name . '\']==1:} checked="checked"{/if}';
            } else {
                $checked = ($value == 1) ? ' checked="checked"' : '';
            }
            $tips = str_contains($vo['form_tips'], '|') ? $vo['form_tips'] : '开启|关闭';
            $input = $this->make_switch($name, $checked, $tips, $attr);
        } elseif ($vo['form_type'] == 'color') {
            // 生成颜色选择器
            $tips = $vo['form_tips'] ?: '请选择颜色';
            $input = $this->make_color($name, $value, $tips, $attr);
        } elseif ($vo['form_type'] == 'image') {
            // 生成图片上传
            $input = $this->make_image($name, $value, $vo['form_tips'], $attr, $options, $mode);
        } elseif ($vo['form_type'] == 'file') {
            // 生成文件上传
            $input = $this->make_file($name, $value, $attr, $options, $mode);
        } else {
            // 生成输入框
            $tips = $vo['form_tips'] ?: '请输入' . $vo['field_title'];
            if ($vo['form_type'] == 'city') {
                // 生成省市区
                $attr['data-toggle'] = 'city-picker';
            } else if ($vo['form_type'] == 'number') {
                // 生成数字
                $attr['type'] = 'number';
                $attr['lay-affix'] = 'number';
            } else if ($vo['form_type'] == 'datetime') {
                // 生成日期时间
                $attr['class'] = 'layui-input datetime';
            }
            $input = $this->make_input($name, $value, $tips, $attr);
        }
        if (isset($attr['type']) && $attr['type'] == 'hidden') {
            return $input;
        }
        $required = $vo['form_required'] ? ' layui-form-item-required' : ''; // 必填标记
        $style = $vo['input_style'] ?: 'layui-input-block'; // 表单项样式
        return "<div class=\"layui-form-item\">\n\t<label class=\"layui-form-label{$required}\">{$vo['field_title']}</label>\n\t<div class=\"{$style}\">{$input}</div>{$append}\n</div>\n";
    }

    protected function make_switch(string $name, string $checked, string $tips, array $attr = []): string
    {
        $attr['lay-text'] = $tips;
        $attr = $this->_attr_str($attr);
        return '<input type="hidden" name="' . $name . '" value="0" /><input type="checkbox" name="' . $name . '" value="1" lay-skin="switch" ' . $checked . $attr . '/>';
    }

    protected function make_color(string $name, $value, string $tips, array $attr = []): string
    {
        $attr['class'] ??= 'layui-input';
        $attr['placeholder'] = $tips;
        $attr = $this->_attr_str($attr);
        $input = '<input type="text" name="' . $name . '" id="c-' . $name . '" value="' . $value . '"' . $attr . '/>';
        return $input.'<div class="layui-input-suffix"><div class="colorpicker" style="margin-left:-16px;" data-input-id="c-' . $name . '" lay-options="{color: \'' . $value . '\'}"></div></div>';
    }

    protected function make_image(string $name, $value, string $tips = '', array $attr = [], array $options = [], int $mode = 1): string
    {
        if (empty($tips)) {
            $tips = '上传图片';
        }
        $attr = $this->_attr_str($attr);
        $input = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . $value . '" ' . $attr . '/>';
        $api = $options['api'] ?? 'image';
        $upload_api = ($mode == 2) ? url('api/upload').'?api='.$api : '{:url(\'api/upload\')}?api='.$api; //上传api
        $select_api = ($mode == 2) ? url('attach/selected').'?type=image&dialog=1' : '{:url(\'attach/selected\')}?type=image&dialog=1'; //选择api
        $input .= '<div class="upload-image layui-upload-drag aphp-upload" id="ID-upload-image-' . $name . '" data-url="'.$upload_api.'" data-accept="image" data-field="' . $name . '">';
        $empty = '<img id="' . $name . '-preview" src="" style="display:none;" width="90" height="60" alt="' . $name . '">' . $tips . '<span id="' . $name . '-remove" class="remove-pic">删除</span>';
        $has = '<img id="' . $name . '-preview" src="' . $value . '" width="90" height="60" alt="' . $name . '">' . $tips . '<span id="' . $name . '-remove" class="remove-pic" style="display: inline;">删除</span>';
        if ($mode == 1) {
            $input .= '{empty $vo[\''.$name.'\']:}'.$empty.'{else:}'.$has.'{/empty}';
        } else {
            $input .= empty($value) ? $empty : $has;
        }
        return $input.'</div><button type="button" class="layui-btn layui-btn-sm" id="' . $name . '-selected" data-url="' . $select_api . '">图库选择</button>';
    }

    protected function make_file(string $name, $value, array $attr = [], array $options = [], int $mode = 1): string
    {
        $attr['lay-affix'] = 'clear';
        $attr['placeholder'] ??= '请上传文件';
        $attr['class'] ??= 'layui-input';
        $attr = $this->_attr_str($attr);
        $input = '<input type="text" name="' . $name . '" id="' . $name . '" value="' . $value . '" ' . $attr . '/>';
        $api = $options['api'] ?? 'zip';
        $type = $options['type'] ?? 'zip';
        $file_type = Config::init()->get('upload.file_type', ['image' => 'jpg|jpeg|gif|png']);
        if (!isset($file_type[$type])) {
            $type = '';
        }
        $exts = ($api == 'file') ? implode('|', $file_type) : $file_type[$type];
        $btn_attr = ' data-accept="file"';
        $accept = 'file';
        if ($type == 'image' || $type == 'audio' || $type == 'video') {
            $btn_attr = ' data-accept="'.$type.'"';
            $accept = $type;
        }
        if (!empty($exts)) {
            $btn_attr .= ' lay-options="{accept:\''.$accept.'\',exts:\''.$exts.'\'}"';
        }
        $upload_api = ($mode == 2) ? url('api/upload').'?api='.$api : '{:url(\'api/upload\')}?api='.$api; //上传api
        $select_api = ($mode == 2) ? url('attach/selected').'?type='.$type.'&dialog=1' : '{:url(\'attach/selected\')}?type='.$type.'&dialog=1'; //选择api
        $btn_upload = '<button type="button" class="layui-btn layui-btn-normal aphp-upload" id="ID-upload-' . $name . '" data-url="' . $upload_api . '" data-field="' . $name . '"' . $btn_attr . '><i class="layui-icon layui-icon-upload" style="color:#fff;"></i> 上传</button>';
        $btn_select = '<button type="button" class="layui-btn" id="' . $name . '-selected" data-url="' . $select_api . '"><i class="layui-icon layui-icon-slider" style="color:#fff;"></i> 选择</button>';
        return '<div class="layui-col-xs7">'.$input.'</div><div class="layui-col-xs5">&nbsp;'.$btn_upload.' '.$btn_select.'</div>';
    }

    protected function make_input(string $name, $value, string $tips, array $attr = []): string
    {
        $type = $attr['type'] ?? 'text';
        if (isset($attr['type'])) unset($attr['type']);
        if ($type != 'hidden') {
            $attr['placeholder'] = $tips;
            $attr['class'] ??= 'layui-input';
        }
        $attr = $this->_attr_str($attr);
        return '<input type="' . $type . '" name="' . $name . '" value="' . $value . '" ' . $attr . '/>';
    }

    // 选项处理
    protected function _parse_options(array $vo, int $mode = 0)
    {
        $vo['dict_id'] ??= 0;
        if (in_array($vo['form_type'], ['radio', 'select', 'selects'])) {
            if ($mode == 2) {
                $options = ($vo['dict_id'] > 0) ?  widget('dict')->get($vo['dict_id']) : str_to_array($vo['form_options']);
                return $options ?: ['未设置'];
            }
            return ($vo['dict_id'] > 0) ? 'widget(\'dict\')->get('.$vo['dict_id'].')' : 'widget(\'model_field_options\')->get('.$vo['id'].')';
        }
        return str_to_array($vo['form_options']);
    }

    // 值处理
    protected function _parse_value(array $vo, int $mode = 1): string
    {
        if ($mode == 1) {
            if (in_array($vo['form_type'], ['radio', 'select', 'selects'])) {
                return '$vo[\'' . $vo['field_name'] . '\']';
            }
            $options = $this->_parse_options($vo, $mode);
            $func = isset($options['function']) ? $this->_parse_func($options['function']) : '';
            return '{$vo.' . $vo['field_name'] .$func. '}';
        }
        if ($mode == 2) {
            return $vo['field_value'];
        }
        return $vo['form_value'];
    }

    // 函数处理
    protected function _parse_func(string $func): string
    {
        $args = '';
        if (str_contains($func, ':')) {
            [$func, $args] = explode(':', $func, 2);
        }
        if (function_exists($func)) {
            if (!empty($args)) {
                $args = explode(',', $args);
                $args = array_map(fn($v) => (!is_numeric($v) && !in_array($v, ['true', 'false'])) ? '\''.$v.'\'' : $v, $args);
                $args = '='.implode(',', $args);
            }
            return '|'.$func .$args;
        }
        return '';
    }

    // 属性转换字符串
    protected function _attr_str(array $attr): string
    {
        if (empty($attr)) {
            return '';
        }
        $str = '';
        foreach ($attr as $k => $v) {
            $str .= is_numeric($k) ? ' '.$v : ' '.$k . '="' . $v . '"';
        }
        return $str;
    }

    // 生成表头
    public function makeTableCols(array $vo): string
    {
        // 属性
        $col_attr = str_to_array($vo['col_attr']);
        $attr = '';
        foreach ($col_attr as $k => $v) {
            if (is_numeric($k) || $k == 'maxWidth') {
                continue;
            }
            $v = (!is_numeric($v) && !in_array($v, ['true', 'false'])) ? '\''.$v.'\'' : $v;
            $attr .= ','.$k.':'.$v;
        }
        // 选项
        $selectList = '';
        if (in_array($vo['form_type'], ['radio', 'select', 'selects']) || $vo['form_type'] == 'switch') {
            // 动态属性
            if ($vo['form_type'] == 'switch') {
                $st = ['开启','关闭'];
                if (str_contains($vo['form_tips'], '|')) {
                    $st = explode('|', $vo['form_tips'], 2);
                }
                $selectList = ', selectList: { 0: \''.$st[1].'\', 1: \''.$st[0].'\' },tips: \''.$st[0].'|'.$st[1].'\'';
            } else {
                $options = ($vo['dict_id'] > 0) ? 'widget(\'admin.dict\')->get('.$vo['dict_id'].')' : 'widget(\'admin.model_field_options\')->get('.$vo['id'].')';
                $selectList = ', selectList: {:select_list('.$options.')}';
            }
        }
        // 模板
        $template = '';
        if (!empty($vo['col_tpl'])) {
            $template = str_starts_with($vo['col_tpl'], '<') ? '\''.str_replace("'", "\'", $vo['col_tpl']).'\'' : $vo['col_tpl'];
            $template = ', templet: '.$template;
        }
        // 搜索
        $search = '';
        if ($vo['col_search'] != 'true') {
            $search = ($vo['col_search'] == 'false')? ', search: false' : ', search: \''.$vo['col_search'].'\'';
        }
        if ($vo['col_search'] != 'false' && $vo['col_search_op'] != '=') {
            $search .= ', searchOp: \''.$vo['col_search_op'].'\'';
        }
        return "{ title: '{$vo['field_title']}', field: '{$vo['field_name']}'{$template}{$selectList}{$attr}{$search} },";
    }
}